package com.itheima.blog.admin.dto;


import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.itheima.blog.admin.utils.*;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import javax.validation.constraints.Min;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "分页结果")
public class PageDTO<T> {
    @ApiModelProperty("总条数")
    protected Long total;
    @ApiModelProperty("总页码数")
    protected Long pages;
    @ApiModelProperty("当前页数据")
    protected List<T> list;

    public static <T> PageDTO<T> empty(Long total, Long pages) {
        return new PageDTO<>(total, pages, CollUtils.emptyList());
    }
    public static <T> PageDTO<T> empty(Page<?> page) {
        return new PageDTO<>(page.getTotal(), page.getPages(), CollUtils.emptyList());
    }

    public static <T> PageDTO<T> of(Page<T> page) {
        if(page == null){
            return new PageDTO<>();
        }
        if (CollUtils.isEmpty(page.getRecords())) {
            return empty(page);
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), page.getRecords());
    }
    public static <T,R> PageDTO<T> of(Page<R> page, Function<R, T> mapper) {
        if(page == null){
            return new PageDTO<>();
        }
        if (CollUtils.isEmpty(page.getRecords())) {
            return empty(page);
        }
        return new PageDTO<>(page.getTotal(), page.getPages(),
                page.getRecords().stream().map(mapper).collect(Collectors.toList()));
    }
    public static <T> PageDTO<T> of(Page<?> page, List<T> list) {
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }

    public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz) {
        return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz));
    }

    public static <T, R> PageDTO<T> of(Page<R> page, Class<T> clazz, Convert<R, T> convert) {
        return new PageDTO<>(page.getTotal(), page.getPages(), BeanUtils.copyList(page.getRecords(), clazz, convert));
    }

    @ApiModelProperty(hidden = true)
    @JsonIgnore
    public boolean isEmpty(){
        return list == null || list.size() == 0;
    }

    @Data
    @ApiModel(description = "分页请求参数")
    @Accessors(chain = true)
    public static class PageQuery {
        public static final Integer DEFAULT_PAGE_SIZE = 20;
        public static final Integer DEFAULT_PAGE_NUM = 1;

        @ApiModelProperty(value = "页码", example = "1")
        @Min(value = 1, message = "页码不能小于1")
        private Integer pageNo = DEFAULT_PAGE_NUM;

        @ApiModelProperty(value = "每页大小", example = "5")
        @Min(value = 1, message = "每页查询数量不能小于1")
        private Integer pageSize = DEFAULT_PAGE_SIZE;

        @ApiModelProperty(value = "是否升序", example = "true")
        private Boolean isAsc = true;

        @ApiModelProperty(value = "排序字段", example = "id")
        private String sortBy;

        public int from(){
            return (pageNo - 1) * pageSize;
        }

        public <T> Page<T> toMpPage(OrderItem... orderItems) {
            Page<T> page = new Page<>(pageNo, pageSize);
            // 是否手动指定排序方式
            if (orderItems != null && orderItems.length > 0) {
                for (OrderItem orderItem : orderItems) {
                    page.addOrder(orderItem);
                }
                return page;
            }
            // 前端是否有排序字段
            if (StringUtils.isNotEmpty(sortBy)){
                OrderItem orderItem = new OrderItem();
                orderItem.setAsc(isAsc);
                orderItem.setColumn(sortBy);
                page.addOrder(orderItem);
            }
            return page;
        }

        public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc) {
            if (StringUtils.isBlank(sortBy)){
                sortBy = defaultSortBy;
                this.isAsc = isAsc;
            }
            Page<T> page = new Page<>(pageNo, pageSize);
            OrderItem orderItem = new OrderItem();
            orderItem.setAsc(this.isAsc);
            orderItem.setColumn(sortBy);
            page.addOrder(orderItem);
            return page;
        }
        public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
            return toMpPage(Constant.DATA_FIELD_NAME_CREATE_TIME, false);
        }
    }
}
